/*=========================================================================
 Copyright (c) 2008, Nokia Corporation and/or its subsidiary(-ies).
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of the Nokia Corporation and/or its subsidiary(-ies)nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=========================================================================================*/

#ifndef NCVVECTOR_H
#define NCVVECTOR_H

#include "ncvFixed.h"	// Added by ClassView
#include "ncvMatrix.h"

/*! \enum TVectorType
 *  \brief Enum type of possible vectors
 * \note Symbian TClass.
 */
enum TVectorType
	{
	EHorizontalVector,
	EVerticalVector
	};
/**
 * \class CNokiaCVVector
 * \brief Fixed point representation of a vector
 */
class CNokiaCVVector : public CNokiaCVMatrix
	{
private:
	CNokiaCVVector();

	/*!
	 * \brief The actual constructor for NewL(const TInt aSize, const TVectorType aType)
	 *		  and the corresponding special cases
	 * \param aSize - the length of the vector
	 * \return A pointer to the created vector
	 */
	void ConstructL(const TInt aSize, const TVectorType aType);
	/*!
	 * \brief The actual constructor for NewL(const TInt aSize, const TVectorType aType)
	 *		  and the corresponding special cases
	 * \param aSize - the length of the vector
	 * \return A pointer to the created vector
	 */	
	void ConstructL(const TInt aSize, const TVectorType aType, const CFixed** array);	

public:
	IMPORT_C virtual ~CNokiaCVVector();

public:

	/*!
	 * \brief Constructs a new CNokiaCVVector according to the given type and size
	 * \param aSize - the length of the vector
	 * \param aType - vector type EVertical or EHorizontal
	 * \note the function can leave (NewL)
	 * \return A pointer to the created vector
	 */
	IMPORT_C static CNokiaCVVector* NewL( const TInt aSize, const TVectorType aType);
	/*!
	 * \brief Constructs a new CNokiaCVVector according to the given type and size
	 * \param aSize - the length of the vector
	 * \param aType - vector type EVertical or EHorizontal
	 * \note the function can leave (NewL)
	 * \return A pointer to the created vector
	 */
	IMPORT_C static CNokiaCVVector* CNokiaCVVector::NewL( const TInt aSize, const TVectorType aType, const CFixed** array);	
	/*!
	 * \brief Constructs a new CNokiaCVVector according to the given type and size
	 *        with initial value zero (same as NewL)
	 * \param aSize - the length of the vector
	 * \param aType - vector type EVertical or EHorizontal
	 * \note the function can leave
	 * \return A pointer to the created vector
	 */
	IMPORT_C static CNokiaCVVector* Zero( const TInt aSize, const TVectorType aType);

	/*!
	 * \brief Constructs a new Horizontal CNokiaCVVector according to the given type and size
	 *        with initial value zero (same as NewL(aSize, EHorizontalVector))
	 * \param aSize - the length of the vector
	 * \note the function can leave
	 * \return A pointer to the created vector
	 */
	IMPORT_C static CNokiaCVVector* Horizontal( const TInt aSize);

	/*!
	 * \brief Constructs a new Vertical CNokiaCVVector according to the given type and size
	 *        with initial value zero (same as NewL(aSize, EHorizontalVector))
	 * \param aSize - the length of the vector
	 * \note the function can leave
	 * \return A pointer to the created vector
	 */
	IMPORT_C static CNokiaCVVector* Vertical( const TInt aSize);
	
	/*!
	 * \brief Constructs an unit vector where the element at parameter aNonZeroIndex equals one,
	 * 		  others zero e.g. e = [0 0 0 0 1 0]  aNonZeroIndex = 4
	 * \param aSize - the length of the vector
	 * \param aType - the vector type
	 * \param aNonZeroIndex - the index of the non-zero element
	 * \note the function can leave
	 * \return A pointer to the created vector
	 */
	IMPORT_C static CNokiaCVVector* Unit( const TInt aSize, const TVectorType aType, const TInt aNonZeroIndex);

	/*!
	 * \brief Getter of the vector type
	 * \return The type of this vector
	 */
	IMPORT_C TVectorType Type();

	/*!
	 * \brief Getter of the vector size/length
	 * \return The type of this vector
	 */
	IMPORT_C TInt Size();

	/*!
	 * \brief Getter of the vector size/length
	 * \return The type of this vector
	 */
	IMPORT_C TInt Length();


	/** @name Matrix Norms
		 */

	/*!
	* \brief Calculates the L2-norm of a vector,
	*        no matter on the type of the vector
	* \note the function can leave
	* \return The L2-norm of this vector
	*/
	IMPORT_C CFixed Norm2();
	/*!
	* \brief Calculates the L1-norm of a vector
	* 		  no matter on the type of the vector
	* \return The L1-norm of this vector
	*/
	IMPORT_C CFixed Norm();
	/*!
	* \brief Calculates the LInf-norm of a vector
	* 		  no matter on the type of the vector
	* \return The LInf-norm of this vector
	*/
	IMPORT_C CFixed NormInf();
	//@}

	/*!
	* \brief Creates the transpose vector of this vector,
	*
	* 		  no matter on the type of the vector
	* \return The LInf-norm of this vector
	*
	*	Overrides the Matrix transpose and changes the type also.
	*  KErrNoMemory thrown, if not enough memory to create a new vector
	* \note the function can leave
	*/
	IMPORT_C CNokiaCVVector* Transpose() const;

	/*!
	* \brief Calculates the sum of squared distances of
	*		  this and a given vector. KErrArgument thrown, if
	*		  size and type don't match.
	* \param The corresponding vector
	* \return SSD of this and the given vector
	* \note This function is a Leaving function even though the name DOESN'T have an L
	*/
	IMPORT_C CFixed SSD(CNokiaCVVector &aV);

	/*!
	 * \brief Creates the normalization of this vector.
	 * \note the function can leave
	 * \return The normalized vector
	 *	KErrNoMemory thrown if not enough memory
	 */
	IMPORT_C CNokiaCVVector* Normalize();

	/*!
	 * \brief Calculates the magnitude of this vector
	 * \return The magnitude of this vector
	 */
	IMPORT_C CFixed Magnitude();

	/*!
	 * \brief Calculates the square magnitude of this vector
	 * \return The magnitude of this vector
	 */
	IMPORT_C CFixed SquareMagnitude();

	/*!
	 * \brief Calculates the cross product of this and the given vector
	 * \param aVector - the vector with which the product is counted with
	 * \return The product vector
	 *
	 * \note KErrArgument is thrown, if sizes don't match.
	 *  of if the size of either one of the vectors is zero or
	 *  greater then three. If the size of the vectors is 1, returns a
	 *  zero vector of size three, if the vector size is two returns a vector of
	 *  size three, where the only non-zero element is k-element
	 * \note the function can leave
	 */
	IMPORT_C CNokiaCVVector* CrossProduct(CNokiaCVVector &aVector);

	/*!
	 * \brief Calculates the dot product of to same size vectors
	 * \param aVector - the vector with which the product is counted with
	 * \return The DotProduct of two vectors
	 * \note the function can leave
	 */
	IMPORT_C CFixed DotProduct(CNokiaCVVector &aVector);

	/*!
	* \brief Calculates the Mahalanobis distance (x-y)'M^-1(x-y)
	* 		  of this and the given vector and covariance matrix
	* \param aVectorB the other vector (y)
	* \param aCovMatrix the covariance matrix
	* \return The Mahalanobis distance
	*
	* \note KErrArgument is thrown, if sizes don't match or the vectors aren't the same type.
	* \note the function can leave
	*
	*/
	IMPORT_C CFixed Mahalanobis(CNokiaCVVector &aVectorB, CNokiaCVMatrix &aCovMatrix);

   /** @name Operations
	* \brief Basic vector operations. 
	*
	*  \note Every operation throws a KErrArgument error,
	*  if the operation is not allowed for the given vector e.g. when size
	*  dose not match.
	*/
	//@{

	/*!
	 * \brief Getter and setter for the element at the give index, type doesn't matter
	 * \param aIndex - the index number (starting from zero) from where to set/get an element
	 * \return the corresponding element in the vector
	 */
	IMPORT_C CFixed& operator()(const TInt aIndex);

	IMPORT_C CNokiaCVVector& operator =(const CNokiaCVVector& aVector);

	IMPORT_C TBool operator ==(const CNokiaCVVector& aVector);	
	//IMPORT_C TBool operator_eqeq(const CNokiaCVVector& aVector);

	IMPORT_C TBool operator !=(const CNokiaCVVector& aVector);
	//IMPORT_C TBool operator_noteq(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVVector* operator +(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVVector& operator +=(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVVector* operator -(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVVector& operator -=(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVMatrix* operator*(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVVector* operator*(const CFixed aScalar);

	IMPORT_C CNokiaCVVector& operator *=(const CFixed aScalar);

	/*!
	 * \brief Although a division is not defined for a vector one is implemented,
	 *		  that calculates multiplication with this and 1/aVector, where aVector is given.
	 * \param aVector - the divider
	 * \return the division of this and the given vector
	 */
	IMPORT_C CNokiaCVMatrix* operator /(const CNokiaCVVector& aVector);

	IMPORT_C CNokiaCVVector* operator /(const CFixed aScalar);

	IMPORT_C CNokiaCVVector& operator /=(const CFixed aScalar);
	//@}


private:
	/*!
	 * \brief The type of this vector
	 */
	TVectorType iType;

	/*!
	 * \brief The size of this vector
	 */
	TInt iSize;

	};

#endif
